package com.diaohw.platform.common.util;


import cn.hutool.core.util.StrUtil;
import com.diaohw.platform.common.enums.CodeMsgEnum;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.type.TypeFactory;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
import java.util.Map;


/**
 * json工具类
 *
 * @author bairh
 * @date 2023/5/18 9:41
 */
@Slf4j
public class JsonUtil {

    private static final ObjectMapper MAPPER = JacksonUtil.createObjectMapper();


    /**
     * 转换为Jackson自身的JavaType
     */
    public static JavaType convertToJavaType(Type type) {
        return TypeFactory.defaultInstance().constructType(type);
    }

    /**
     * 转换为Jackson自身的JavaType
     */
    public static JavaType convertToJavaType(TypeReference<?> typeReference) {
        return TypeFactory.defaultInstance().constructType(typeReference);
    }

    /**
     * 对象转Json格式字符串
     *
     * @param object 对象
     * @return Json格式字符串
     */
    public static String toJsonString(Object object) {
        if (object == null) {
            return null;
        }
        if (object instanceof String) {
            return (String) object;
        }
        try {
            return MAPPER.writeValueAsString(object);
        } catch (Exception e) {
            log.error("method=toJson() is convert error, errorMsg:{}", e.getMessage(), e);
            return null;
        }
    }


    /**
     * 格式化json格式字符串
     *
     * @param object 对象
     * @return Json格式字符串
     */
    public static String toJsonPrettyString(Object object) {
        if (object == null) {
            return null;
        }
        if (object instanceof String) {
            return (String) object;
        }
        try {
            return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(object);
        } catch (Exception e) {
            log.error("method=toJson() is convert error, errorMsg:{}", e.getMessage(), e);
            return null;
        }
    }


    /**
     * Object TO Json String 字符串输出(输出空字符)
     *
     * @param object 对象
     * @return Json格式字符串
     */
    public static String toJsonEmpty(Object object) {
        if (object == null) {
            return null;
        }
        try {
            MAPPER.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
                @Override
                public void serialize(Object param, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                    //设置返回null转为 空字符串""
                    jsonGenerator.writeString("");
                }
            });
            return MAPPER.writeValueAsString(object);
        } catch (Exception e) {
            log.error("method=toJsonEmpty() is convert error, errorMsg:{}", e.getMessage(), e);
        }
        return null;
    }


    /**
     * Json 转为 Map
     *
     * @param text json
     * @param <K>  key
     * @param <V>  value
     * @return map
     */
    public static <K, V> Map<K, V> toMap(String text) {
        try {
            if (StrUtil.isEmpty(text)) {
                return Collections.emptyMap();
            }
            return toBean(text, new TypeReference<>() {
            });
        } catch (Exception e) {
            log.error("method=toMap() is convert error, errorMsg:{}", e.getMessage(), e);
        }
        return Collections.emptyMap();
    }


    /**
     * Json 转 List, Class 集合中泛型的类型，非集合本身
     *
     * @param text json
     * @param <T>  对象类型
     * @return List
     */
    public static <T> List<T> toList(String text, Class<T> clazz) {
        if (StrUtil.isEmpty(text)) {
            return Collections.emptyList();
        }
        try {
            return MAPPER.readerForListOf(clazz).readValue(text);
        } catch (Exception e) {
            log.error("method=toList() is convert error, errorMsg:{}", e.getMessage(), e);
        }
        return Collections.emptyList();
    }

    /**
     * Json 转 List, Class 集合中泛型的类型，非集合本身
     *
     * @param text json
     * @param <T>  对象类型
     * @return List
     */
    public static <T> List<T> toList(String text, TypeReference<List<T>> listTypeReference) {
        if (StrUtil.isEmpty(text)) {
            return Collections.emptyList();
        }
        try {
            return MAPPER.readValue(text, listTypeReference);
        } catch (Exception e) {
            log.error("method=toList() is convert error, errorMsg:{}", e.getMessage(), e);
        }
        return Collections.emptyList();
    }


    /**
     * Json 转为 Java Bean
     *
     * @param text json
     * @param <T>  类型
     * @return T
     */
    public static <T> T toBean(String text, JavaType javaType) {
        try {
            return MAPPER.readValue(text, javaType);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw CodeMsgEnum.JSON.build(e.getMessage());
        }
    }


    /**
     * Json 转为 Java Bean
     *
     * @param text          json
     * @param typeReference TypeReference
     * @param <T>           类型
     * @return T
     */
    public static <T> T toBean(String text, TypeReference<T> typeReference) {
        try {
            return MAPPER.readValue(text, typeReference);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw CodeMsgEnum.JSON.build(e.getMessage());
        }
    }

    /**
     * Json 转为 Java Bean
     *
     * @param text  json
     * @param clazz class
     * @param <T>   类型
     * @return T
     */
    public static <T> T toBean(String text, Class<T> clazz) {
        try {
            return MAPPER.readValue(text, clazz);
        } catch (JsonProcessingException e) {
            log.error("method=toObject() is convert error, errorMsg:{}", e.getMessage(), e);
            throw CodeMsgEnum.JSON.build(e.getMessage());
        }
    }

    /**
     * Json 转为 Java Bean
     *
     * @param bytes json
     * @param type  Type
     * @param <T>   类型
     * @return T
     */
    @SuppressWarnings("unchecked")
    public static <T> T toBean(byte[] bytes, Type type) {
        try {

            return MAPPER.readValue(bytes, convertToJavaType(type));
        } catch (Exception e) {
            log.error("method=toObject() is convert error, errorMsg:{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * Json str 转为 Java Bean
     *
     * @param str  jsonStr
     * @param type Type
     * @param <T>  类型
     * @return T
     */
    @SuppressWarnings("unchecked")
    public static <T> T toBean(String str, Type type) {
        try {

            return MAPPER.readValue(str, convertToJavaType(type));
        } catch (Exception e) {
            log.error("method=toObject() is convert error, errorMsg:{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * Json 转为 Java Bean
     *
     * @param bytes json
     * @param clazz class
     * @param <T>   类型
     * @return T
     */
    @SuppressWarnings("unchecked")
    public static <T> T toBean(byte[] bytes, Class<T> clazz) {
        try {

            return MAPPER.readValue(bytes, clazz);
        } catch (Exception e) {
            log.error("method=toObject() is convert error, errorMsg:{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * Json 转为 Java Bean
     *
     * @param node  json node
     * @param clazz class
     * @param <T>   类型
     * @return T
     */
    public static <T> T toBean(JsonNode node, Class<T> clazz) {
        try {
            return MAPPER.treeToValue(node, clazz);
        } catch (JsonProcessingException e) {
            throw CodeMsgEnum.JSON.build(e.getMessage());
        }
    }

    /**
     * Json 转为 Java Bean
     *
     * @param node json node
     * @param type class
     * @param <T>  类型
     * @return T
     */
    public static <T> T toBean(JsonNode node, TypeReference<T> type) {
        JavaType javaType = convertToJavaType(type);
        return toBean(node, javaType);

    }


    /**
     * Json 转为 Java Bean
     *
     * @param node json node
     * @param type type
     * @param <T>  类型
     * @return T
     */
    public static <T> T toBean(JsonNode node, Type type) {
        try {
            JavaType javaType = convertToJavaType(type);
            return MAPPER.treeToValue(node, javaType);
        } catch (JsonProcessingException e) {
            throw CodeMsgEnum.JSON.build(e.getMessage());
        }
    }

    public static JsonNode toJsonNode(Object object) {
        return MAPPER.valueToTree(object);
    }

    /**
     * toBytes
     */
    public static byte[] toBytes(Object data) {
        try {
            return MAPPER.writeValueAsBytes(data);
        } catch (Exception e) {
            e.printStackTrace();
            throw CodeMsgEnum.JSON.build(e.getMessage());
        }

    }

}
